import {Injectable, OnModuleInit} from "@nestjs/common";
import {Repository} from "typeorm";
import {SysUser} from "../entity/SysUser";
import {InjectRepository} from "@nestjs/typeorm";
import {Result} from "../common/Result";
import {JwtConstant} from "../common/constant/JwtConstant";
import {BusinessException} from "../common/exception/BusinessException";
import config from "../config";
import {SysRole} from "../entity/SysRole";
import {StatusEnum} from "../common/enum/StatusEnum";
import {RoleEnum} from "../common/enum/RoleEnum";
import {INIT_CONSTANTS} from "../InitProjectConstant";
import {PageQuery} from "../common/page/PageQuery";
import {SysUserDto} from "../dto/SysUserDto";
import {CollectionUtils} from "../common/utils/CollectionUtils";


@Injectable()
export class SysUserService implements OnModuleInit{
    @InjectRepository(SysUser)
    private userRepository: Repository<SysUser>

    /**
     * 用户初始化
     */
    async onModuleInit() {
        if (!config.doInit) {
            return;
        }
        let acc = INIT_CONSTANTS.users.usernames;
        let name = INIT_CONSTANTS.users.names;
        let password = '123456';
        let list: SysUser[] = [];
        for (let i = 0; i < acc.length; i++) {
            let sysUser = new SysUser();
            sysUser.id = i+1;
            sysUser.username = acc[i];
            sysUser.name = name[i];
            sysUser.password = JwtConstant.encryptPassword(password);
            sysUser.status = 1;
            sysUser.isDefault = 1;
            sysUser.init(1);

            let role = new SysRole();
            let roleid = i + 1;
            role.roleId = roleid == RoleEnum.ADMIN.code? roleid : roleid == 2? roleid : RoleEnum.STORE_ASSISTANT.code;
            sysUser.roles = [role];

            list.push(sysUser);
        }
        await this.userRepository.query(`delete from sys_user_role where user_id in (1, 2, 3, 4)`);
        await this.userRepository.save(list).then(r => {
            console.log("初始化用户成功!");
        });
    }

    /**
     * 用户详情
     * @param user
     */
    async findDetails(user: SysUser): Promise<SysUser>{
        const { username } = user;
        return await this.userRepository.findOne({ where: {username}, relations: ["roles"] });
    }

    /**
     * 通过账号查询用户
     * @param username 账号
     */
    async findOne(username: string): Promise<SysUser> {
        return await this.userRepository.findOneBy({username, status: StatusEnum.AVAILABLE});
    }

    /**
     * 注册用户
     * @param user
     */
    async registerUser(user:SysUser): Promise<Result<any>>{
        let {username, password} = user;
        let one: SysUser = await this.userRepository.findOneBy({username});
        if (one) {
            throw new BusinessException('用户已存在!');
        }
        user.password = JwtConstant.encryptPassword(password);
        await this.userRepository.save(user);
        return Result.success("注册成功!");
    }

    /**
     * 添加用户
     * @param user
     */
    async addUser(user: SysUserDto) {
        let {username, password} = user;
        let one: SysUser = await this.userRepository.findOneBy({username});
        if (one) {
            throw new BusinessException('用户已存在!');
        }
        user.password = JwtConstant.encryptPassword(password);
        // let sysUser = new SysUser();
        // sysUser.username = username;
        // sysUser.password = password;
        // sysUser.name = user.name;
        // sysUser.roles = user.roles;
        user.init(JwtConstant.getUserId());
        await this.userRepository.save(user)
        return Result.success();
    }

    /**
     * 编辑用户
     * @param user
     */
    async editUser(user: SysUser): Promise<Result<any>> {
        let one = await this.userRepository.findOneBy({username: user.username});
        if (one && one.id != user.id) {
            return Result.failed('用户已存在!');
        } else if (!one) {
            return Result.failed('数据异常!');
        }
        let { password } = user;
        // 密码加密
        user.password = JwtConstant.encryptPassword(password);
        let res = await this.userRepository.update(user.id, user);
        return Result.success('编辑成功');
    }

    /**
     * 用户列表
     * @param query
     */
    async userList(query: PageQuery<SysUserDto>) {
        let param = query.param;
        let queryBuilder = this.userRepository.createQueryBuilder("u")
            .select([
                "u.id as userId",
                "u.name as userName",
                "u.username as account",
                "u.is_default as isDefault",
                "u.status as status",
                "r.role_id as roleId",
                "r.role_name as roleName"
            ])
            // .addSelect("r.role_name", "roleName")
            .leftJoin("sys_user_role" , "ur", `ur.user_id = u.id`)
            .leftJoin("sys_role", "r", "ur.role_id = r.role_id")
            .where("1=1");
        if (param?.username) {
            queryBuilder.andWhere(`u.username like '%${param.username}%'`);
        }
        if (param?.name) {
            queryBuilder.andWhere(`u.name like '%${param.name}%'`);
        }
        if (param?.roleId) {
            queryBuilder.andWhere(`r.role_id = ${param.roleId}`)

        }
        // // let list = await queryBuilder.skip(PageQuery.skip(query)).take(query.pageSize).getRawMany();
        // let list = await queryBuilder.offset(PageQuery.skip(query)).limit(query.pageSize).getRawMany();
        // let number = await queryBuilder.getCount();
        // return [list, number];
        return await PageQuery.getRawManyAndCount(query, queryBuilder);
    }

    /**
     * 用户详情查询2
     * @param query
     */
    async sysUserQuery(query: SysUserDto) {

        // return await this.userRepository.findOne({ where: {id: query.userId}, relations: ["roles"]})

        let sysUser = await this.userRepository.createQueryBuilder("u")
            .select()
            .leftJoin("sys_user_role", "ur", `ur.user_id = u.id`)
            // .leftJoin("sys_role", "r", "ur.role_id = r.role_id")
            .leftJoinAndMapMany("u.roles", "sys_role", "r", "ur.role_id = r.role_id")
            .where(`u.id = ${query.id}`)
            .getOne();

        let vo = new SysUserDto();
        Object.keys(sysUser).forEach(key => {
            vo[key] = sysUser[key];
        })
        vo.roleId = sysUser.roles[0]?.roleId;
        return vo;
    }

    /**
     * 删除用户
     */
    async deleteUser(user: SysUser) {
        let one = await this.userRepository.findOne({ where: {id: user.id}, relations:["roles"] });
        if (!one) {
            return Result.failed("数据异常!");
        }
        await this.userRepository.remove(one);
        return Result.success();
    }

    /**
     * 修改用户
     * @param user
     */
    async updateUser(user: SysUserDto) {
        let data = await this.userRepository.findOne({ where: { id: user.id}, relations: ["roles"] });
        if (!data) {
            return Result.failed("数据异常!");
        }
        data.username = user.username;
        data.name = user.name;
        if (user.newPwd) {
            data.password = JwtConstant.encryptPassword(user.newPwd);
        }
        data.roles = data.roles?.filter(item => {
           return user.roleId == item.roleId;
        })
        if (CollectionUtils.isEmpty(data.roles)) {
            let role = new SysRole();
            role.roleId = user.roleId;
            data.roles = [...data.roles, role];
        }
        data.initUpdate(JwtConstant.getUserId());
        await this.userRepository.save(data);
        return Result.success();
    }
}
